package version4.common.serializer.MySerializer.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import version4.common.Message.RpcRequest;
import version4.common.Message.RpcResponse;
import version4.common.serializer.MySerializer.Serializer;

public class JSONSerializer implements Serializer {
    @Override
    public byte[] serialize(Object data) {
        return JSONObject.toJSONBytes(data);
    }

    @Override
    public Object deserialize(byte[] bytes, int messageType) {
        Object obj = null;
        switch (messageType) {
            case 0:
                // 请求,反序列化请求对象
                RpcRequest request = JSON.parseObject(bytes, RpcRequest.class);
                // fastjson 反序列化时，无法反序列化 Class<?>[] 或者 Object[] 类型，需要手动处理
                Object[] objects = new Object[request.getParams().length];
                for (int i = 0; i < objects.length; i++) {
                    Class<?> paramType = request.getParamsType()[i];
                    if(!paramType.isAssignableFrom(request.getParams()[i].getClass())) {
                        objects[i] = JSONObject.toJavaObject((JSONObject) request.getParams()[i], paramType);
                    }else{
                        objects[i] = request.getParams()[i];
                    }
                }
                request.setParams(objects);
                obj = request;
                break;
            case 1:
                RpcResponse response = JSON.parseObject(bytes, RpcResponse.class);

                Class<?> dataType = response.getDataType();
                // 加一步判空操作，防止空指针异常
                if(response.getCode() == 200 && !dataType.isAssignableFrom(response.getData().getClass())) {
                    response.setData(JSONObject.toJavaObject((JSONObject) response.getData(), dataType));
                }
                obj = response;
                break;
            default:
                throw new RuntimeException("不支持的消息类型");
        }
        return obj;
    }

    @Override
    public int getType() {
        return 1;
    }
}
